#pragma once
// OpenGLControl.cpp : implementation file
//

#include "stdafx.h"
#include "mfcPuppy.h"
#include "OpenGLControl.h"


GLfloat COpenGLControl::global_ambient[4]		= {0.2f, 0.2f, 0.2f, 1.0f};
GLfloat COpenGLControl::light0Pos[4]			= {-2.0f, -4.0f, -2.0f, 1.0f};
GLfloat COpenGLControl::light0Amb[4]			= {0.2f, 0.2f, 0.2f, 1.0f};
GLfloat COpenGLControl::light0Diff[4]			= {0.3f, 0.3f, 0.3f, 1.0f};
GLfloat COpenGLControl::light0Spec[4]			= {0.4f, 0.4f, 0.4f, 1.0f};


GLfloat COpenGLControl::light1Pos[4]			= {0.0f, 1.6f, -5.0f, 1.0f};
GLfloat COpenGLControl::light1Amb[4]			= {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat COpenGLControl::light1Diff[4]			= {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat COpenGLControl::light1Spec[4]			= {1.0f, 1.0f, 1.0f, 1.0f};

GLfloat COpenGLControl::shadow_ambient[4]		= {0.0f, 0.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::shadow_diffuse[4]		= {0.0f, 0.0f, 0.0f, 0.3f};
GLfloat COpenGLControl::shadow_shiny			= 0.0f;
GLfloat COpenGLControl::shadow_specular[4]		= {0.0f, 0.0f, 0.0f, 1.0f};

GLfloat COpenGLControl::wall_color[4]			= {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat COpenGLControl::wall_ambient[4]			= {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat COpenGLControl::floor_color[4]			= {0.5f, 1.0f, 0.5f, 0.5f};
GLfloat COpenGLControl::column_color[4]			= {1.0f, 0.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::column_ambient[4]		= {0.25f, 0.0f, 0.0f, 1.0f};

GLfloat COpenGLControl::cube_color[4]			= {1.0f, 1.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::cube_shiny				= 99.0f;
GLfloat COpenGLControl::cube_specular[4]		= {0.9f, 0.9f, 0.9f, 1.0f};
GLfloat COpenGLControl::cube_ambient[4]			= {0.1f, 0.1f, 0.1f, 1.0f};

GLfloat COpenGLControl::lamp_post_diffuse[4]	= {0.8f, 0.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::lamp_post_specular[4]	= {0.8f, 0.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::lamp_post_ambient[4]	= {0.25f, 0.0f, 0.0f, 1.0f};

GLfloat COpenGLControl::target_ambient[4]		= {0.3f, 0.3f, 0.3f, 0.7f};
GLfloat COpenGLControl::target_diffuse[4]		= {0.3f, 0.3f, 0.3f, 0.7f};
GLfloat COpenGLControl::target_specular[4]		= {0.3f, 0.3f, 0.3f, 0.7f};

GLfloat COpenGLControl::target_post_diffuse[4]	= {0.8f, 0.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::target_post_specular[4]	= {0.8f, 0.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::target_post_ambient[4]	= {0.25f, 0.0f, 0.0f, 1.0f};


GLfloat COpenGLControl::specular[4]				= {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat COpenGLControl::emissive[4]				= {0.0f, 0.0f, 0.0f, 1.0f};
GLfloat COpenGLControl::shininess				= 128.0f;

enum displayLists {
	ground=1100, left_wall, right_wall, // boundary walls
	column, two_columns, four_columns,  // columns
	lamp_post, lamp,				 	// lights
	left_wall_shadow_matrix,			// shadows
	shadow_lamp_base,
	shadow_end_effector };

static float mvt_x = -15.0f;static float mvt_y = -15.0f;
static float mvt_z = -30.7f;

static float mvr_d = 150.0f;
static float mvr_x = 1.0f;
static float mvr_y = -1.0f;
static float mvr_z = -1.0f;

static float cube_vertexes[6][4][4] ={
  {
    {-1.0, -1.0, -1.0, 1.0},
    {-1.0, -1.0, 1.0, 1.0},
    {-1.0, 1.0, 1.0, 1.0},
    {-1.0, 1.0, -1.0, 1.0}},

  {
    {1.0, 1.0, 1.0, 1.0},
    {1.0, -1.0, 1.0, 1.0},
    {1.0, -1.0, -1.0, 1.0},
    {1.0, 1.0, -1.0, 1.0}},

  {
    {-1.0, -1.0, -1.0, 1.0},
    {1.0, -1.0, -1.0, 1.0},
    {1.0, -1.0, 1.0, 1.0},
    {-1.0, -1.0, 1.0, 1.0}},

  {
    {1.0, 1.0, 1.0, 1.0},
    {1.0, 1.0, -1.0, 1.0},
    {-1.0, 1.0, -1.0, 1.0},
    {-1.0, 1.0, 1.0, 1.0}},

  {
    {-1.0, -1.0, -1.0, 1.0},
    {-1.0, 1.0, -1.0, 1.0},
    {1.0, 1.0, -1.0, 1.0},
    {1.0, -1.0, -1.0, 1.0}},

  {
    {1.0, 1.0, 1.0, 1.0},
    {-1.0, 1.0, 1.0, 1.0},
    {-1.0, -1.0, 1.0, 1.0},
    {1.0, -1.0, 1.0, 1.0}}
};

static float cube_normals[6][4] =
{
  {-1.0, 0.0, 0.0, 0.0},
  {1.0, 0.0, 0.0, 0.0},
  {0.0, -1.0, 0.0, 0.0},
  {0.0, 1.0, 0.0, 0.0},
  {0.0, 0.0, -1.0, 0.0},
  {0.0, 0.0, 1.0, 0.0}
};


void subDivide(float u1[3], float u2[3], float u3[3], int depth)
{
	float u12[3];
	float u23[3];
	float u31[3];

	int i;

	if (depth == 0) {

	 glBegin (GL_POLYGON);
		 glNormal3f (0.0, 0.0, 1.0); glVertex3fv(u1);
		 glNormal3f (0.0, 0.0, 1.0); glVertex3fv(u2);
		 glNormal3f (0.0, 0.0, 1.0); glVertex3fv(u3);
	 glEnd();
	 return;
	}

	for (i = 0; i < 3; i++) {
		u12[i] = (u1[i] + u2[i]) / 2.0f;
		u23[i] = (u2[i] + u3[i]) / 2.0f;
		u31[i] = (u3[i] + u1[i]) / 2.0f;
	}

	subDivide(u1, u12, u31, depth - 1);
	subDivide(u2, u23, u12, depth - 1);
	subDivide(u3, u31, u23, depth - 1);
	subDivide(u12, u23, u31, depth - 1);

}

void drawGround(void)
{
	/// <summary>
	/// Use two subdivided triangles for the unscaled 1X1 square.
	/// </summary>
	int maxdepth = 2;

	// Coordinates of first triangle:
	float u1[] = {-1.0, -1.0, 0.0};
	float u2[] = {1.0, -1.0, 0.0};
	float u3[] = {1.0, 1.0, 0.0};
	// Coordinates of second triangle:
	float v1[] = {-1.0, -1.0, 0.0};
	float v2[] = {1.0, 1.0, 0.0};
	float v3[] = {-1.0, 1.0, 0.0};

	subDivide(u1, u2, u3, maxdepth);
	subDivide(v1, v2, v3, maxdepth);
}

static void drawCube(GLfloat color[4], GLfloat ambient[4])
{
	int i;
	glMaterialfv(GL_FRONT, GL_DIFFUSE, color);
	glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
	for (i = 0; i < 6; ++i) {
		glNormal3fv(&cube_normals[i][0]);
		glBegin(GL_POLYGON);
			glVertex4fv(&cube_vertexes[i][0][0]);
			glVertex4fv(&cube_vertexes[i][1][0]);
			glVertex4fv(&cube_vertexes[i][2][0]);
			glVertex4fv(&cube_vertexes[i][3][0]);
		glEnd();
	}
}

// COpenGLControl

IMPLEMENT_DYNAMIC(COpenGLControl, CWnd)

COpenGLControl::COpenGLControl()
{
   	/// <summary>
	/// variables for camera functions -- zoom, translate, rotate
	/// </summary>
	m_fLastX	= 0.0f;
	m_fLastY	= 0.0f;
	m_fPosX		= 0.0f;		// X position of model in camera view
	m_fPosY		= 0.0f;		// Y position of model in camera view
	m_fZoom		= 10.0f;	// Zoom on model in camera view
	m_fRotX		= 0.0f;		// Rotation on model in camera view
	m_fRotY		= 0.0f;		// Rotation on model in camera view

	/// <summary>
	/// drawing scene variables
	/// </summary>
	GLfloat value[4]		= {0.0f, 0.0f, 0.0f, 0.0f};	// value to be displayed
	GLfloat target[4]		= {0.0f, 0.0f, 0.0f, 0.0f};	// target value
	quadratic				= gluNewQuadric();			// pointer to the Quadric object
														// used for creating spheres & disks


}

COpenGLControl::~COpenGLControl()
{
	gluDeleteQuadric(quadratic);
}

BEGIN_MESSAGE_MAP(COpenGLControl, CWnd)
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_CREATE()
	ON_WM_TIMER()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()


// COpenGLControl message handlers


void COpenGLControl::OnPaint()
{
	ValidateRect(NULL); // Remove the entire window from the update region used by WM_PAINT.
						// In other words, don't bother updating the window
}

void COpenGLControl::OnSize(UINT nType, int cx, int cy)
{
	CWnd::OnSize(nType, cx, cy);

	if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;

	// Map the OpenGL coordinates.
	glViewport(0, 0, cx, cy);

	// Projection view
	glMatrixMode(GL_PROJECTION);

	glLoadIdentity();

	// Set our current view perspective
	gluPerspective(35.0f, (float)cx / (float)cy, 0.01f, 200.0f);

	// Model view
	glMatrixMode(GL_MODELVIEW);

	MoveWindow(0, 0, cx, cy); // This is the MFC window.

}

int COpenGLControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	oglInitialize();

	return 0;
}

void COpenGLControl::OnDraw(CDC *pDC)
{
	glLoadIdentity();
	glTranslatef(0.0, 0.0, -5.0); // shifts the origin to the center of the world
	//glTranslatef(0.0, 0.0, -m_fZoom);
	glTranslatef(m_fPosX, m_fPosY, 0.0f);
	glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);
	glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
	glTranslatef(0.0f, 0.0f, -m_fZoom +5.0);
}

void COpenGLControl::OnTimer(UINT_PTR nIDEvent)
{
	switch (nIDEvent)
	{
		case 1:
		{
			// Clear color and depth buffer bits
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			// Draw OpenGL scene
			//oglDrawScene();
			oglDrawHMScene();

			// Swap buffers -- note: Windows specific
			SwapBuffers(hdc);

			break;
		}

		default:
			break;
	}
	
	CWnd::OnTimer(nIDEvent);
}

void COpenGLControl::OnMouseMove(UINT nFlags, CPoint point)
{
	int diffX = (int)(point.x - m_fLastX);
	int diffY = (int)(point.y - m_fLastY);
	m_fLastX  = (float)point.x;
	m_fLastY  = (float)point.y;

	// Left mouse button
	if (nFlags & MK_LBUTTON)
	{
		m_fRotX += (float)0.5f * diffY;

		if ((m_fRotX > 360.0f) || (m_fRotX < -360.0f))
		{
			m_fRotX = 0.0f;
		}

		m_fRotY += (float)0.5f * diffX;

		if ((m_fRotY > 360.0f) || (m_fRotY < -360.0f))
		{
			m_fRotY = 0.0f;
		}
	}

	// Middle mouse button
	else if (nFlags & MK_MBUTTON)
	{
		m_fZoom += (float)0.1f * diffY;
	}

	// Right mouse button
	else if (nFlags & MK_RBUTTON)
	{
		m_fPosX += (float)0.05f * diffX;
		m_fPosY -= (float)0.05f * diffY;
	}

	OnDraw(NULL);

	CWnd::OnMouseMove(nFlags, point);
}

BOOL COpenGLControl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	// TODO: Add your message handler code here and/or call default


	m_fZoom -= (float)0.005f * zDelta;
	OnDraw(NULL);

	return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}

void COpenGLControl::oglCreate(CRect rect, CWnd *parent)
{
   CString className = AfxRegisterWndClass(CS_HREDRAW |
      CS_VREDRAW | CS_OWNDC, NULL,
      (HBRUSH)GetStockObject(BLACK_BRUSH), NULL);

   CreateEx(0, className, L"OpenGL", WS_CHILD | WS_VISIBLE |
            WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);

   hWnd = parent;
}

void COpenGLControl::oglInitialize(void)
{
   // Initial Setup:
   //
	static PIXELFORMATDESCRIPTOR pfd =
	{
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		32,    // bit depth
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		16,    // z-buffer depth
		0, 0, 0, 0, 0, 0, 0,
	};

	// Get device context only once.
	hdc = GetDC()->m_hDC;

	// Pixel format.
	m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
	SetPixelFormat(hdc, m_nPixelFormat, &pfd);

	// Create the OpenGL Rendering Context.
	hrc = wglCreateContext(hdc);
	wglMakeCurrent(hdc, hrc);

	// Basic Setup:
	//
	// Set color to use when clearing the background.
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glClearDepth(1.0f);

	// Turn on backface culling
	glFrontFace(GL_CCW);
	glCullFace(GL_BACK);

	// Turn on depth testing
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	// Initialize the drawing scene specific variables
	oglHMSceneInit();

	// Send draw request
	OnDraw(NULL);
}

void COpenGLControl::oglHMSceneInit(void)
{
	// Turn on lighting models with smooth shading
	glEnable(GL_LIGHTING);
	glShadeModel(GL_SMOOTH);

	gluQuadricNormals(quadratic, GLU_SMOOTH);	// Create Smooth Normals
	gluQuadricTexture(quadratic, GL_TRUE);		// Create Texture Coords
	
	//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
	//glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
	//glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
	//glLightfv(GL_LIGHT0, GL_AMBIENT, light0Amb);
	//glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diff);
	//glLightfv(GL_LIGHT0, GL_SPECULAR, light0Spec);
	//glEnable(GL_LIGHT0);
	/// <summary>	///	setup light sources	/// </summary>
	//glLightfv(GL_LIGHT1, GL_POSITION, COpenGLControl::light1Pos);
	glLightfv(GL_LIGHT1, GL_AMBIENT, COpenGLControl::light1Amb);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, COpenGLControl::light1Diff);
	glLightfv(GL_LIGHT1, GL_SPECULAR, COpenGLControl::light1Spec);
	glEnable(GL_LIGHT1);
	glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.07);


	/// <summary>
	/// setup call lists
	/// Essentially, these images are rendered in the GPU and stored.
	/// This allows for quick drawing for these pre-rendered images, 
	/// instead of having to render them at every frame.
	/// </summary>

	// Ground list
	glNewList(ground, GL_COMPILE);
		glPushMatrix();
			glPushAttrib(GL_LIGHTING_BIT);
				glMaterialfv(GL_FRONT, GL_DIFFUSE, COpenGLControl::floor_color);
				glMaterialfv(GL_FRONT, GL_AMBIENT, COpenGLControl::shadow_ambient);
				glTranslatef(0.0, -1.5, -5.0);
				glRotatef(-90.0, 1, 0, 0);
				glScalef(5.0, 5.0, 1.0);
					drawGround();
			glPopAttrib();
		glPopMatrix();
	glEndList();

	// lamp post list - used for target	glNewList(lamp_post, GL_COMPILE);
		glPushMatrix();
			glPushAttrib(GL_LIGHTING_BIT);
			glMaterialfv(GL_FRONT, GL_AMBIENT, lamp_post_specular);
			glTranslatef(0.0, -0.775, -5.0);
			glScalef(0.03, 0.675, 0.03);
				drawCube(COpenGLControl::lamp_post_diffuse, COpenGLControl::lamp_post_ambient);
			glPopAttrib();
		glPopMatrix();
	glEndList();

	// 
	//// lamp -- used for target and end effector
	//glNewList(lamp, GL_COMPILE);
		//glPushMatrix();
		//	glPushAttrib(GL_LIGHTING_BIT);
		//	glMaterialfv(GL_FRONT, GL_AMBIENT, lamp_ambient);
		//	glMaterialfv(GL_FRONT, GL_DIFFUSE, lamp_diffuse);
		//	glMaterialfv(GL_FRONT, GL_SPECULAR, lamp_specular);
		//	glTranslatef(0.0, 0.0, -5.0);
		//		glutWireSphere(0.3, 8.0, 3.0);   
		//	glPopAttrib();
		//glPopMatrix();
	//glEndList();


	// left wall
	glNewList(left_wall, GL_COMPILE);
		glPushMatrix();
		glPushAttrib(GL_LIGHTING_BIT);
				glMaterialfv(GL_FRONT, GL_DIFFUSE, COpenGLControl::wall_color);
				glMaterialfv(GL_FRONT, GL_AMBIENT, COpenGLControl::wall_ambient);
				glTranslatef(0.0, 0.0, -5.0);
				glTranslatef(-5.0, 0.0, 0.0);
				glRotatef(90.0, 0, 1, 0);
				glScalef(4.5, 1.2, 1.0);
				glNormal3f (0.0, 0.0, 1.0);
					drawGround();
		glPopAttrib();
		glPopMatrix();
	glEndList();

	// right wall
	glNewList(right_wall, GL_COMPILE);
		glPushMatrix();
		glPushAttrib(GL_LIGHTING_BIT);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, COpenGLControl::wall_color);
			glMaterialfv(GL_FRONT, GL_AMBIENT, COpenGLControl::wall_ambient);
			glTranslatef(0.0, 0.0, -5.0);
			glTranslatef(5.0, 0.0, 0.0);
			glRotatef(270.0, 0, 1, 0);
			glScalef(4.5, 1.2, 1.0);
			glNormal3f (0.0, 0.0, 1.0);      
				drawGround();
		glPopAttrib();
		glPopMatrix();
	glEndList();


	// column components
	glPushMatrix();
		// column - middle
		glNewList(1, GL_COMPILE); 
			glPushMatrix();
				glScalef(0.4, 1.4, 0.4);
				drawCube(COpenGLControl::column_color, COpenGLControl::column_ambient);
			glPopMatrix();
		glEndList();

		// column - base and top
		glNewList(2, GL_COMPILE);
			glPushMatrix();
				glTranslatef(0.0, -1.45, 0.0);
				glScalef(0.5, 0.1, 0.5);
				drawCube(COpenGLControl::wall_color, COpenGLControl::cube_ambient); // base
			glPopMatrix();
			glPushMatrix();
				glTranslatef(0.0, 1.45, 0.0);
				glScalef(0.5, 0.1, 0.5);
				drawCube(COpenGLControl::wall_color, COpenGLControl::cube_ambient); // top
			glPopMatrix();
		glEndList();
	glPopMatrix();

	// individual column
	glNewList(column, GL_COMPILE);
		glPushMatrix();
			glCallList(1);
			glCallList(2);
		glPopMatrix();
	glEndList();

	// columns in front, left to right
	glNewList(4, GL_COMPILE);
		glPushMatrix();
			glTranslatef(-5.0, 0.0, -0.5);
			glCallList(column);	
		glPopMatrix();
	glEndList();       	
	glNewList(5, GL_COMPILE);
		glPushMatrix();
			glTranslatef(-1.7, 0.0, -0.5);
			glCallList(column);	
		glPopMatrix();
	glEndList();       
	glNewList(6, GL_COMPILE);
		glPushMatrix();
			glTranslatef(1.7, 0.0, -0.5);
			glCallList(column);	
		glPopMatrix();
	glEndList();       
	glNewList(17, GL_COMPILE);
		glPushMatrix();
			glTranslatef(5.0, 0.0, -0.5);
			glCallList(column);	
		glPopMatrix();
	glEndList();     


	// four columns for the front and back of the scenes
	glNewList(four_columns, GL_COMPILE);
		glPushMatrix();
			glCallList(4);
			glCallList(5);
			glCallList(6);
			glCallList(17);
		glPopMatrix();
	glEndList();

	// two columns for the left and right of the scenes
	glNewList(two_columns, GL_COMPILE);
		glPushMatrix();
			glRotatef(90.0, 0.0, 1.0, 0.0);
			glTranslatef(5.0, 0.0, -5.0);
				glPushMatrix();
					glTranslatef(0.0, 0.0, -0.3);
					glCallList(column);
				glPopMatrix();
				glPushMatrix();
					glTranslatef(0.0, 0.0, 10.3);
					glCallList(column);
				glPopMatrix();
		glPopMatrix();
	glEndList();

	//// shadow of the lamp post base
	//glNewList(shadow_lamp_base, GL_COMPILE);
	//	glPushMatrix();
	//	glPushAttrib(GL_LIGHTING_BIT);
	//		glMaterialfv(GL_FRONT, GL_SPECULAR, shadow_specular);
	//		glMaterialfv(GL_FRONT, GL_SHININESS, shadow_shiny);
	//		glTranslatef(0.0, -1.49, -5.0);
	//		glScalef(0.35, 0.0, 0.42);
	//			drawCube(shadow_diffuse, shadow_ambient);
	//	glPopAttrib();
	//	glPopMatrix();
	//glEndList();


	// end effector shadow	glNewList(shadow_end_effector, GL_COMPILE);		glPushMatrix();
		glPushAttrib(GL_LIGHTING_BIT);
			glMaterialfv(GL_FRONT, GL_SPECULAR, COpenGLControl::shadow_specular);
			glMaterialf(GL_FRONT, GL_SHININESS, COpenGLControl::shadow_shiny);
			glTranslatef(0.0, -1.49, 0.0);
			glRotatef(-90, 1, 0, 0);
			gluDisk(quadratic, 0, 1, 20, 20);
		glPopAttrib();
		glPopMatrix();
	glEndList();

  // define other lists here


}

void COpenGLControl::oglDrawScene(void)
{
   // Wireframe Mode
   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

   glBegin(GL_QUADS);
      // Top Side
      glVertex3f( 1.0f, 1.0f,  1.0f);
      glVertex3f( 1.0f, 1.0f, -1.0f);
      glVertex3f(-1.0f, 1.0f, -1.0f);
      glVertex3f(-1.0f, 1.0f,  1.0f);

      // Bottom Side
      glVertex3f(-1.0f, -1.0f, -1.0f);
      glVertex3f( 1.0f, -1.0f, -1.0f);
      glVertex3f( 1.0f, -1.0f,  1.0f);
      glVertex3f(-1.0f, -1.0f,  1.0f);

      // Front Side
      glVertex3f( 1.0f,  1.0f, 1.0f);
      glVertex3f(-1.0f,  1.0f, 1.0f);
      glVertex3f(-1.0f, -1.0f, 1.0f);
      glVertex3f( 1.0f, -1.0f, 1.0f);

      // Back Side
      glVertex3f(-1.0f, -1.0f, -1.0f);
      glVertex3f(-1.0f,  1.0f, -1.0f);
      glVertex3f( 1.0f,  1.0f, -1.0f);
      glVertex3f( 1.0f, -1.0f, -1.0f);

      // Left Side
      glVertex3f(-1.0f, -1.0f, -1.0f);
      glVertex3f(-1.0f, -1.0f,  1.0f);
      glVertex3f(-1.0f,  1.0f,  1.0f);
      glVertex3f(-1.0f,  1.0f, -1.0f);

      // Right Side
      glVertex3f( 1.0f,  1.0f,  1.0f);
      glVertex3f( 1.0f, -1.0f,  1.0f);
      glVertex3f( 1.0f, -1.0f, -1.0f);
      glVertex3f( 1.0f,  1.0f, -1.0f);
   glEnd();
}

void COpenGLControl::oglDrawHMScene(void)
{
	/// <summary>
	/// setup lights
	/// </summary>
	glPushMatrix();
		glLightfv(GL_LIGHT1, GL_POSITION, COpenGLControl::light1Pos);
	glPopMatrix();

	/// <summary>	/// draw floor	/// </summary>	glPushMatrix();
		glCallList(ground);
	glPopMatrix();

	/// <summary>	/// draw boundaries	/// </summary>
	glCallList(left_wall);		// left
	glCallList(right_wall);		// right
	glCallList(four_columns);	// front
	glPushMatrix();				
		glTranslatef(0.0, 0.0, -9.0);
		glCallList(four_columns); // rear
	glPopMatrix();
	glCallList(two_columns);	// left and right columns
	

	/// <summary>	/// draw target	/// </summary>	glPushMatrix();		SetTargetMaterial();		drawTarget();
	glPopMatrix();

	/// <summary>
	/// draw endeffector & shadow
	/// </summary>
	float r = 0.2; // radius of the end effector
	float scaleFactor = -r*(value[1]-1.5)/3 + 0.1*r;
	glPushMatrix();
		//SetDisplayMaterial();
		glTranslatef(value[0], value[1], value[2]);
		// draw end-effector		gluSphere(quadratic, r, 50, 50);
		// draw shadow		glEnable(GL_BLEND);		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glMaterialfv(GL_FRONT, GL_SPECULAR, COpenGLControl::shadow_specular);
		glMaterialf(GL_FRONT, GL_SHININESS, COpenGLControl::shadow_shiny);
		glTranslatef(0.0, -value[1], 0.0);
		glScalef(scaleFactor, 1.0, scaleFactor);
			glCallList(shadow_end_effector);		glDisable(GL_BLEND);
	glPopMatrix();

	///// <summary>	///// draw gimbal	///// </summary>	//glPushMatrix();
	//	glTranslatef(value[0], value[1], value[2]);
	//	//SetGimbalGoodMaterial();
	//	//or
	//	//SetGimbalBadMaterial();
	//	//glRotatef(OpenGLParams.currentGimbal[GimbalDOF] * GimbalScale, 0, 0, 1);
	//	for (int i = 0; i < 6; i++) 
	//	{
	//		glNormal3fv(&cube_normals[i][0]);
	//		glBegin(GL_POLYGON);
	//			glVertex4fv(&cube_vertexes[i][0][0]);
	//			glVertex4fv(&cube_vertexes[i][1][0]);
	//			glVertex4fv(&cube_vertexes[i][2][0]);
	//			glVertex4fv(&cube_vertexes[i][3][0]);
	//		glEnd();
	//	}	//glPopMatrix();
}

void COpenGLControl::drawTarget(void)
{
	float r = 0.3f; // radius of the target sphere
	//float dx = (float) (ForceParams.targetForce[Y_AXIS]/OpenGLParams.scale * 5.0  + 0.0); // SGI.x-axis = LAB.y-axis. OpenGL.x = Lab.Fy / displayScale *  10/2 + 0.0
	//float dy = (float) (ForceParams.targetForce[Z_AXIS]/OpenGLParams.scale * 1.5  + 0.0); // SGI.y-axis = LAB.z-axis. OpenGL.y = Lab.Fz / displayScale *   3/2 + 0.0	//float dz = (float) (ForceParams.targetForce[X_AXIS]/OpenGLParams.scale * 4.5  - 5.0);  // SGI.z-axis = LAB.x-axis. OpenGL.z = Lab.Fx / displayScale *  9/2 - 5.0
	float l_2 = (value[1] - r/2 + 1.5f) / 2.0f; // base of post - (center of light - half-of-radius of the lamp)

	float scaleFactor = -r*(value[1] - 1.5f)/3.0f + 0.1f*r; // radius of the disk for the shadow

	/// <summary>
	/// target lamp post
	/// </summary>
	glPushMatrix();
		glPushAttrib(GL_LIGHTING_BIT);
			glMaterialfv(GL_FRONT, GL_AMBIENT, COpenGLControl::target_post_specular);
			glTranslatef(value[0], value[1] - l_2 - r/2, value[2]);
			glScalef(0.03, l_2, 0.03);
			drawCube(COpenGLControl::target_post_diffuse, COpenGLControl::target_post_ambient); //draw the target lamp post
		glPopAttrib();
	glPopMatrix();

	/// <summary>
	/// target lamp
	/// </summary>
	glPushMatrix();
		glPushAttrib(GL_LIGHTING_BIT);
			glMaterialfv(GL_FRONT, GL_AMBIENT, COpenGLControl::target_ambient);
			glMaterialfv(GL_FRONT, GL_DIFFUSE, COpenGLControl::target_diffuse);
			glMaterialfv(GL_FRONT, GL_SPECULAR, COpenGLControl::target_specular);
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glTranslatef(value[0], value[1], value[2]);
				gluSphere(quadratic, r, 20.0, 20.0); // draw the target sphere
				// draw shadow
				glTranslatef(0.0, -value[1], 0.0);
				glScalef(scaleFactor, 1.0, scaleFactor);
					glCallList(shadow_end_effector);
			glDisable(GL_BLEND);
		glPopAttrib();
	glPopMatrix();
}

void COpenGLControl::SetTargetMaterial(void)
{
	//Sets the target display material parameters
	glMaterialfv(GL_FRONT, GL_AMBIENT, COpenGLControl::target_ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, COpenGLControl::target_diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, COpenGLControl::specular);
	glMaterialfv(GL_FRONT, GL_EMISSION, COpenGLControl::emissive);
	glMaterialf(GL_FRONT, GL_SHININESS, COpenGLControl::shininess);

}